﻿using System;
using System.ComponentModel;
using Castle.DynamicProxy;

namespace TimeKeeper.Infrastructure
{
    public class PropertyChangedInterceptor : IInterceptor
    {
        private PropertyChangedEventHandler _handler;

        public virtual void Intercept(IInvocation invocation)
        {
            var methodName = invocation.Method.Name;

            if (invocation.Method.DeclaringType != null && invocation.Method.DeclaringType == typeof(INotifyPropertyChanged))
            {
                if (methodName == "add_PropertyChanged")
                    _handler = (PropertyChangedEventHandler)Delegate.Combine(_handler, (Delegate)invocation.Arguments[0]);
                if (methodName == "remove_PropertyChanged")
                    _handler = (PropertyChangedEventHandler)Delegate.Remove(_handler, (Delegate)invocation.Arguments[0]);

                return;
            }

            Object originalValue = null;

            if (methodName.StartsWith("set_"))
            {
                originalValue = invocation.Proxy.GetType().GetProperty(methodName.Substring(4)).GetValue(invocation.Proxy, null);
            }

            invocation.Proceed();

            if (methodName.StartsWith("set_") && !Equals(originalValue, invocation.Arguments[0]))
            {
                OnPropertyChanged(invocation.Proxy, new PropertyChangedEventArgs(methodName.Substring(4)));
            }
        }

        protected virtual void OnPropertyChanged(Object sender, PropertyChangedEventArgs e)
        {
            var eventHandler = _handler;
            if (eventHandler != null) eventHandler(sender, e);
        }
    }
}
